#include "logger.h"

Logger::Logger() {
	Properties prop;
	//Inicializo el mutex
	mutex = PTHREAD_MUTEX_INITIALIZER;

	if(prop.load(CONFIG_FILE_NAME)) {
		fileName = prop.getProperty("fileName");
		pattern = prop.getProperty("dateTimePattern");
		debugLevel = getIntegerDebugLevel(prop.getProperty("debugLevel"));

		//Creo archivo de log
		loggerFile.open(fileName.c_str(),ios::out | ios::app);

		if(loggerFile.is_open())
			loggerFile.close();
		else
			cout << "Error al crear archivo de log: " << fileName << endl;
	}
}

Logger& Logger::getLoggerInstance() {
	static Logger instance;
	return instance;
}

void Logger::debug(const char *msj, ...) {
	char buffer[SIZE];
	va_list arglist;

	//Cargo el msj el formato y las variables
	va_start(arglist,msj);
	vsprintf(buffer,msj,arglist);
	va_end(arglist);

	if(debugLevel == LOG_DEBUG ) {
		////// Lockeo la region cr�tica //////
		pthread_mutex_trylock(&mutex);

		if(openLogger()){
			loggerFile << printTime()
					   << "DEBUG [" << getpid() << "] - "
					   << buffer << endl;
		}
		closeLogger();

		////// Desbloqueo la region critica //////
		pthread_mutex_unlock(&mutex);
	}
}

void Logger::info(const char *msj, ...) {
	char buffer[SIZE];
	va_list arglist;

	//Cargo el msj el formato y las variables
	va_start(arglist,msj);
	vsprintf(buffer,msj,arglist);
	va_end(arglist);

	if(debugLevel >= LOG_INFO ) {
		////// Lockeo la region cr�tica //////
		pthread_mutex_trylock(&mutex);

		if(openLogger()){
			loggerFile << printTime()
					   << "INFO  [" << getpid() << "] - "
					   << buffer << endl;
		}
		closeLogger();

		////// Desbloqueo la region critica //////
		pthread_mutex_unlock(&mutex);
	}
}

void Logger::warn(const char *msj, ...) {
	char buffer[SIZE];
	va_list arglist;

	//Cargo el msj el formato y las variables
	va_start(arglist,msj);
	vsprintf(buffer,msj,arglist);
	va_end(arglist);

	if(debugLevel >= LOG_WARN ) {
		////// Lockeo la region cr�tica //////
		pthread_mutex_trylock(&mutex);

		if(openLogger()){
			loggerFile << printTime()
					   << "WARN  [" << getpid() << "] - "
					   << buffer << endl;
		}
		closeLogger();

		////// Desbloqueo la region critica //////
		pthread_mutex_unlock(&mutex);
	}
}

void Logger::error(const char *msj, ...) {
	char buffer[SIZE];
	va_list arglist;

	//Cargo el msj el formato y las variables
	va_start(arglist,msj);
	vsprintf(buffer,msj,arglist);
	va_end(arglist);

	if(debugLevel >= LOG_ERROR ) {
		////// Lockeo la region cr�tica //////
		pthread_mutex_trylock(&mutex);

		if(openLogger()){
			loggerFile << printTime()
					   << "ERROR [" << getpid() << "] - "
					   << buffer << endl;
		}
		closeLogger();

		////// Desbloqueo la region critica //////
		pthread_mutex_unlock(&mutex);
	}
}

void Logger::fatal(const char *msj, ...) {
	char buffer[SIZE];
	va_list arglist;

	//Cargo el msj el formato y las variables
	va_start(arglist,msj);
	vsprintf(buffer,msj,arglist);
	va_end(arglist);

	if(debugLevel >= LOG_ERROR ) {
		////// Lockeo la region cr�tica //////
		pthread_mutex_trylock(&mutex);

		if(openLogger()){
			loggerFile << printTime()
					   << "FATAL [" << getpid() << "] - "
					   << buffer << endl;
		}
		closeLogger();

		////// Desbloqueo la region critica //////
		pthread_mutex_unlock(&mutex);
	}
}


Logger::~Logger() {
	pthread_mutex_destroy(&mutex);
	closeLogger();
}


char* Logger::printTime(void)
{
	 char *buffer = new char[SIZE];
	 char *aux;
	 time_t curtime;
	 struct tm *loctime;

	 /* Get the current time.  */
	 curtime = time (NULL);

	 /* Convert it to local time representation.  */
	 loctime = localtime (&curtime);

	 strftime(buffer, SIZE, "%Y-%m-%d %H:%M:%S \n", loctime);

	 aux = strrchr(buffer,'\n');
	 *aux = '\0';

	 return buffer;
}

bool Logger::openLogger(void) {
	loggerFile.open(fileName.c_str(),ios::out | ios::app);

	if(loggerFile.is_open())
		return true;
	else
		return false;
}

bool Logger::closeLogger(void) {
	loggerFile.close();

	if(!loggerFile.is_open())
		return true;
	else
		return false;
}

int Logger::getIntegerDebugLevel(const string &logLevel) {
	int def = 0;
	if(!logLevel.compare("DEBUG"))
		return LOG_DEBUG;
	if(!logLevel.compare("INFO"))
		return LOG_INFO;
	if(!logLevel.compare("WARN"))
		return LOG_WARN;
	if(!logLevel.compare("ERROR"))
		return LOG_ERROR;
	if(!logLevel.compare("FATAL"))
		return LOG_FATAL;
	return def;
}















